
/* Generated by Interface Builder */

#import "IFolderMatrix.h"
#import "TransparentWindow.h"
#import "IDataGroupBrowser.h"
#import "INXBrowserCellWithLinkedObject.h"
#import "IUifNode.h"
#import "InfoD.h"
#import "ITreeNodeD.h"
#import "AcceptWindow.h"
#import "INntpIO.h"
#import "ITreeBrowser.h"
#import "errdebug.h"
#import "data_types.h"

#import <appkit/NXImage.h>
#import <appkit/Application.h>
#import <appkit/ClipView.h>
#import <appkit/ButtonCell.h>
#import <appkit/Font.h>
#import <string.h>

@implementation IFolderMatrix

- initFrame:(NXRect *)frameRect
{
    [super initFrame:frameRect];
    isPalette = YES;
    //default TransparentWindow class
    iTransparentWindowClass = [TransparentWindow class];
    
    return self;
}

- (BOOL)acceptsFirstMouse
{
    return (YES);
}

- selectNewsgroupInBrowser:sender
{
    const char 	*newsgroupName;
    char	strTmp[256];
    
    newsgroupName = [selectedCell title];
    DBG(1,fprintf(stderr,"-- selectCellInBrowser newsgroup = %s\n", 
    							newsgroupName));
    if ([self selectedCell] == [cellList objectAt:0]) {
	// nextStation icon was clicked, initialize newsgroup browser
	//    set root list node first, 
	//    and load cells into column 0
	[oNewsgroupBrowser setRootListnode:
			[[oNewsgroupBrowser iOmodule] subDirectoryOf:nil]];
	[oNewsgroupBrowser loadColumnZero];
	return (self);
    } else {
	// other newsgroup icon(closedFolder icon) was clicked.
	if ([[oNewsgroupBrowser iOmodule] newsGroupMode] == Tree) {
	    // mode of newsgroup browser is tree
	    [oNewsgroupBrowser setPathSeparator:'.'];
	    strTmp[0] = '.'; strTmp[1] = '\0';
	    strncat (strTmp, newsgroupName, sizeof(strTmp)-2);
	    [oNewsgroupBrowser setPath:strTmp];
	} else {
	    // mode is flat
	    [oNewsgroupBrowser setPathSeparator:'/'];
	    strTmp[0] = '/'; strTmp[1] = '\0';
	    strncat (strTmp, newsgroupName, sizeof(strTmp)-2);
	    [oNewsgroupBrowser setPath:strTmp];
	}
	// click selected cell
	[[oNewsgroupBrowser 
	    matrixInColumn:[oNewsgroupBrowser selectedColumn]] sendAction];
	return (self);
    }
}

- setRootName:(char *)rootName
{
    id		rootCell;
    
    // copy root name
    strncpy (iRootName, rootName, (sizeof(iRootName)-1));
    // make root cell
    [self addCol];
    rootCell = [self cellAt:0 :0];
    [rootCell setIcon:NEXTSTATION];
    [rootCell setTitle:iRootName];
//    [self sizeToCells];
    return (rootCell);
}

- mouseDown:(NXEvent *)theEvent
{
    register BOOL	inside;
    int		shouldLoop = YES;
    int 	oldMask;
    NXEvent	*nextEvent;
    NXPoint	hitPoint;
    int		hitRow, hitCol;
    id		hitCell;
    NXRect	cellIconRect;
    NXRect	iconWindowRect;
    id		image, iconWindow;
    NXPoint	offset, mouseLocation;
    
    hitPoint = theEvent->location;
    [self convertPoint:&hitPoint fromView:nil];
    [self getRow:&hitRow andCol:&hitCol forPoint:&hitPoint];
    hitCell = [self cellAt:hitRow :hitCol];
    // cell frame sould be passed to get icon rect for its cell
    [self getCellFrame:&cellIconRect at:hitRow :hitCol];
    [hitCell getIconRect:&cellIconRect];
    DBG(1,fprintf(stderr," cellIconRect.origin.x = %f\t y = %f\n"
    			 " cellIconRect.size.width = %f\t height = %f\n",
			 cellIconRect.origin.x, cellIconRect.origin.y,
			 cellIconRect.size.width, cellIconRect.size.height));

    if (!NXPointInRect(&hitPoint, &cellIconRect) || 
				    strcmp([hitCell title], "") == 0) {
	// if hit point is not in icon or cell does not have title(=blank
	// cell) or hitCell is nextStation icon, return
	DBG(1,fprintf(stderr,"-- not in icon rect or blank cell\n"));
	return (self);
    }
    
    oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
    while (shouldLoop) {
	nextEvent = [NXApp getNextEvent:
				    (NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
	hitPoint = nextEvent->location;
	[self convertPoint:&hitPoint fromView:nil];
	inside = NXPointInRect(&hitPoint, &cellIconRect);
	switch (nextEvent->type) {
	case NX_LMOUSEUP:
	    shouldLoop = NO;
	    if (inside) {
		// click cell,  send action to the target
		//[super mouseDown:nextEvent];
		[self selectCell:hitCell];
		[self sendAction];
	    }
	    break;
	case NX_LMOUSEDRAGGED:
	    if ([hitCell image] == [NXImage findImageNamed:NEXTSTATION]) {
		// can not drag nextStation icon(because it root)
		break;
	    }
	    if (inside) {
		// create icon window and drag it
		iconWindowRect = cellIconRect;

		// convert icon rect(cellIconRect) to global coord.
		[window convertBaseToScreen:&(iconWindowRect.origin)];

		// hitCell is an obj. from ButtonCell, its image will be 
		// used for icon window image
		image = [hitCell image];
		iconWindow = [[iTransparentWindowClass
					allocFromZone:[self zone]] 
    					initForImage:image 
					at:&(iconWindowRect.origin) 
					forView:hitCell];

		// compute the offset from the image's origin to 
		// the mouse location
		offset.x = hitPoint.x - cellIconRect.origin.x;
		offset.y = (cellIconRect.origin.y + cellIconRect.size.height)
							 - hitPoint.y;
		
		// convert mouse down location to screen coord.
		mouseLocation = nextEvent->location;
		[window convertBaseToScreen:&mouseLocation];
		
		// if this FolderMatrix is not palette matrix, remove 
		// my icon image and clear title
		if ([self isPalette] == NO) {
		    [hitCell setImage:[NXImage findImageNamed:BLANKICON]];
		    [hitCell setTitle:""];
		}
		// go into dragging loop in TranseparentWindow
		[iconWindow dragFromMouseDown:&mouseLocation
						 mouseOffset:&offset];
		// iconWindow is freed automatically when dropped
	    }
	    break;
	default:
	    break;
	}
    }
    [window setEventMask:oldMask];
    return (self);
}

- registerCellAt:(int)krow :(int)kcol window:kwindow
{
    NXRect	rect;
    id		kcell;
    id		awindow;

    // if kwindow == nil, use window under view of IFolderMatrix
    if (kwindow == nil) {
	awindow = [self window];
    } else {
	awindow = kwindow;
    }
    if ([awindow respondsTo:@selector(registerRect:forCell:controlView:)]) {
	[self getCellFrame:&rect at:krow :kcol];
	[self convertRect:&rect toView:nil];
	
	kcell = [self cellAt:krow :kcol];
	return ([awindow registerRect:&rect forCell:kcell controlView:self]);
    }
    return nil;
}
	
- unregisterCellAt:(int)krow :(int)kcol window:kwindow
{
    id		kcell;
    id		awindow;

    // if kwindow == nil, use window under view of IFolderMatrix
    if (kwindow == nil) {
	awindow = [self window];
    } else {
	awindow = kwindow;
    }
    
    if ([awindow respondsTo:@selector(registerRect:forCell:controlView:)]) {
	kcell = [self cellAt:krow :kcol];
	return ([awindow unregisterRectForCell:kcell]);
    } else {
	return nil;
    }
}

- registerCells
{
    int		trow, tcol;

    // if our new window's an AcceptWindow, we'll "register" cell frame with it
    if ([window respondsTo:@selector(registerRect:forCell:controlView:)]) {
	tcol = numCols; trow = numRows;
	while(trow--) {
	    while(tcol--) {
		[self registerCellAt:trow :tcol window:window];
	    }
	    tcol = numCols;
	}
    }
    return self;
}

- sizeTo:(float)width :(float)height
{
    DBG(10,fprintf(stderr," martix sizeTo::++++++++"));
    // every time the matrix's frame is resized, we will register cell's 
    // frame to AcceptWindow.
    [self registerCells];

    return ([super sizeTo:width :height]);
}

- (BOOL)isPalette
{
    return isPalette;
}

@end
